package com.example.demo.service;

import com.alibaba.fastjson.JSON;
import com.example.demo.dao.pojo.UserInfo;
import com.example.demo.util.JWTUtils;
import com.example.demo.vo.ErrorCode;
import com.example.demo.vo.LoginResponseVo;
import com.example.demo.vo.Result;
import com.example.demo.vo.params.LoginParams;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import org.apache.commons.codec.digest.DigestUtils;
import java.util.concurrent.TimeUnit;


@Service
@Transactional
public class LoginService {

    @Autowired
    private UserService userService;

    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    // 加密字符串
    private static final String slat = "t4dmw!@#";


    /**
     * 登录
     * @param loginParams
     * @return
     */
    public Result login(LoginParams loginParams){
        /**
         * 1. 检查参数是否合法
         * 2. 根据用户名和密码去 user 表中查询是否存在
         * 3. 如果不存在——登录失败
         * 4. 如果存在，使用 jwt 生成 token 返回给前端
         * 5. token 放入 redis 当中，redis 影射了 token 的 user 信息，并设置过期时间
         * （登录认证时，先认证 token 字符串是否合法，再去 redis 认证是否存在）
        */
        String username = loginParams.getUsername();
        String password = loginParams.getPassword();
        if(!StringUtils.hasLength(username) || !StringUtils.hasLength(password)){
            return Result.fail(ErrorCode.PARAMS_ERROR.getCode(), ErrorCode.PARAMS_ERROR.getMsg());
        }
        // 对密码进行加密
        password = DigestUtils.md5Hex(password + slat);

        UserInfo userInfo = userService.findUser(username, password);
        if(userInfo == null){
            return Result.fail(ErrorCode.ACCOUNT_PWD_NOT_EXIST.getCode(), ErrorCode.ACCOUNT_PWD_NOT_EXIST.getMsg());
        }
        // 生成 token
        String token = JWTUtils.createToken(userInfo.getId());
        System.out.println("token = " + token);
        // 将生成的 token 保存到 redis 中
        redisTemplate.opsForValue().set("TOKEN_" + token, JSON.toJSONString(userInfo), 1, TimeUnit.DAYS);
        // 将 token 返回给前端
        LoginResponseVo loginResponseVo = new LoginResponseVo();
        loginResponseVo.setAdmin(userInfo.getAdmin());
        loginResponseVo.setToken(token);
        return Result.success(loginResponseVo);
    }

    /**
     * 注册
     * @param loginParams
     * @return
     */
    public Result register(LoginParams loginParams){
        /**
         * 1. 判断参数是否合法
         * 2. 判断账户是否存在，存在则返回用户名已经被注册
         * 3. 不存在，则注册用户
         * 4. 生成 token，并存入 redis
         * 6. 注意：加上事务，一旦中间的任何过程出现问题，注册的用户需要回滚
         */
        String username = loginParams.getUsername();
        String password = loginParams.getPassword();
        if(!StringUtils.hasLength(username) || !StringUtils.hasLength(password)){
            return Result.fail(ErrorCode.PARAMS_ERROR.getCode(), ErrorCode.PARAMS_ERROR.getMsg());
        }
        // 查找用户
        UserInfo userInfo = userService.findUserByName(username);
        if(userInfo != null){
            return Result.fail(ErrorCode.ACCOUNT_EXIST.getCode(), ErrorCode.ACCOUNT_EXIST.getMsg());
        }
        // 将用户存到数据库
        password = DigestUtils.md5Hex(password + slat);
        userService.add(username, password);
        // 生成 token
        UserInfo user = userService.findUserByName(username);
        String token = JWTUtils.createToken(user.getId());
        redisTemplate.opsForValue().set("TOKEN_" + token, JSON.toJSONString(user), 1, TimeUnit.DAYS);
        LoginResponseVo loginResponseVo = new LoginResponseVo();
        loginResponseVo.setAdmin(user.getAdmin());
        loginResponseVo.setToken(token);
        return Result.success(loginResponseVo);
    }
}
